package codeUtil

import (
	"fmt"
	"regexp"
	"strings"
)

type SQLQuery struct {
	SelectColumns []string
	FromTable     string
	LeftJoins     []string
	Wheres        []string
	OrderBy       string
	GroupBy       string
}

var sqlKeywords = []string{
	"SELECT", "FROM", "LEFT JOIN", "JOIN", "ON", "WHERE", "AND", "OR", "GROUP BY", "ORDER BY", "HAVING", "LIMIT",
}

func keywordRegex() *regexp.Regexp {
	pattern := strings.Join(sqlKeywords, "|")
	return regexp.MustCompile(`(?i)\b(` + pattern + `)\b`)
}

// ConvertKeywordsToLowercase 函数将输入的 SQL 查询字符串中的关键字转换为小写。
// 参数:
//   - query: 要转换的 SQL 查询字符串。
//
// 返回值:
//   - 转换为小写后的 SQL 查询字符串。
func ConvertKeywordsToLowercase(query string) string {
	re := keywordRegex()
	return re.ReplaceAllStringFunc(query, strings.ToLower)
}

// FormatSQL 函数格式化输入的 SQL 查询字符串，将其转换为小写并去除多余的空格和换行符。
// 参数:
//   - query: 要格式化的 SQL 查询字符串。
//
// 返回值:
//   - 格式化后的 SQL 查询字符串。
func FormatSQL(query string) string {
	// 转小写
	query = ConvertKeywordsToLowercase(query)

	// 替换换行符和空格
	query = strings.ReplaceAll(query, "\n", " ")
	query = strings.ReplaceAll(query, "\t", " ")

	// Remove extra spaces
	query = strings.Join(strings.Fields(query), " ")

	return query
}

// ParseSQL 函数解析输入的 SQL 查询字符串，并返回一个 SQLQuery 结构体和可能的错误。
// 参数:
//   - query: 要解析的 SQL 查询字符串。
//
// 返回值:
//   - SQLQuery: 解析后的 SQL 查询结构体。
//   - error: 如果解析过程中发生错误，则返回错误信息。
func ParseSQL(query string) (sq SQLQuery, err error) {
	query = FormatSQL(query)

	// 获取执行阶段的下标
	selectIndex := strings.Index(query, "select")
	fromIndex := strings.Index(query, "from")
	whereIndex := strings.Index(query, "where")
	leftJoinIndex := strings.Index(query, "left join")
	groupByIndex := strings.Index(query, "group by")
	orderByIndex := strings.Index(query, "order by")
	if selectIndex == -1 || fromIndex == -1 {
		err = fmt.Errorf("invalid SQL query: missing SELECT or FROM clause")
		return
	}

	// 获取查询参数列表
	selectPart := query[selectIndex+len("select") : fromIndex]
	selectPartSplit := strings.Split(selectPart, ", ")
	for _, s := range selectPartSplit {
		// 处理 IFNULL 函数
		if strings.Contains(s, "ifnull(") {
			s = strings.ReplaceAll(s, "ifnull(", "IFNULL(")
			s = strings.ReplaceAll(s, ")", " )")
		}
		sq.SelectColumns = append(sq.SelectColumns, strings.TrimSpace(s))
	}

	// 获取From片段
	fromPart := query[fromIndex+len("from"):]
	if whereIndex != -1 {
		fromPart = query[fromIndex+len("from") : whereIndex]
	}
	if leftJoinIndex != -1 {
		fromPart = query[fromIndex+len("from") : leftJoinIndex]
	}
	sq.FromTable = strings.TrimSpace(fromPart)

	// 获取LeftJoin片段
	if leftJoinIndex != -1 {
		leftJoinPart := query[leftJoinIndex+len("left join"):]
		if whereIndex != -1 {
			leftJoinPart = query[leftJoinIndex+len("left join") : whereIndex]
		}
		for _, s := range strings.Split(leftJoinPart, "left join") {
			sq.LeftJoins = append(sq.LeftJoins, strings.TrimSpace(s))
		}
	}

	// 获取Where片段
	if whereIndex != -1 {
		wherePart := query[whereIndex+len("where"):]

		split := strings.Split(wherePart, "and")
		for i, s := range split {
			if i != len(split)-1 {
				sq.Wheres = append(sq.Wheres, strings.TrimSpace(s))
			}
		}
	}

	// 获取Group片段
	if groupByIndex != -1 {
		groupPart := query[groupByIndex+len("group by"):]
		sq.GroupBy = strings.TrimSpace(groupPart)
	}

	// 获取Order片段
	if orderByIndex != -1 {
		sq.OrderBy = strings.TrimSpace(query[orderByIndex+len("order by"):])
	}

	return
}

// GenerateSquirrelCode 函数根据给定的 SQL 查询字符串生成相应的 Squirrel 代码。
// 参数:
//   - sqlQuery: 要转换的 SQL 查询字符串。
//
// 返回值:
//   - 生成的 Squirrel 代码字符串。
func GenerateSquirrelCode(sqlQuery string) string {

	parsedQuery, err := ParseSQL(sqlQuery)
	if err != nil {
		fmt.Println("Error parsing SQL query:", err)
		return ""
	}

	var selectCodeStr string
	for _, column := range parsedQuery.SelectColumns {
		selectCodeStr += fmt.Sprintf("\n\t\"%s\",", column)
	}

	var leftJoinCodeString string
	for _, join := range parsedQuery.LeftJoins {
		leftJoinCodeString += fmt.Sprintf("\nLeftJoin(\"%s\").", join)
	}

	var whereCodeString string
	for i, where := range parsedQuery.Wheres {
		if i != len(parsedQuery.Wheres)-1 {
			whereCodeString += fmt.Sprintf("\nWhere(\"%s\").", where)
		} else {
			whereCodeString += fmt.Sprintf("\nWhere(\"%s\")", where)
		}
	}

	var groupByCodeString string
	if parsedQuery.GroupBy != "" {
		groupByCodeString = fmt.Sprintf(".\nGroupBy(\"%s\")", parsedQuery.GroupBy)
	}

	var orderByCodeString string
	if parsedQuery.OrderBy != "" {
		orderByCodeString = fmt.Sprintf(".\nOrderBy(\"%s\")", parsedQuery.OrderBy)
	}

	codeStr := fmt.Sprintf(`
squirrel.Select([]string{%s
}...).
From("%s").%s%s%s%s
`, selectCodeStr, parsedQuery.FromTable, leftJoinCodeString, whereCodeString, groupByCodeString, orderByCodeString)

	return codeStr
}
